package com.ehotting.edsta.auth.controller;

import javax.servlet.http.HttpServletRequest;

import com.alibaba.fastjson.JSONObject;
import com.ehotting.eaf.core.constant.CacheConstants;
import com.ehotting.eaf.core.constant.Constants;
import com.ehotting.eaf.core.constant.HttpStatus;
import com.ehotting.eaf.core.constant.SecurityConstants;
import com.ehotting.eaf.core.domain.R;
import com.ehotting.eaf.core.domain.system.api.SysDictData;
import com.ehotting.eaf.core.domain.system.api.SysUser;
import com.ehotting.eaf.core.enums.UserTypeEnum;
import com.ehotting.eaf.core.exception.ServiceException;
import com.ehotting.eaf.core.utils.DateUtils;
import com.ehotting.eaf.core.utils.StringUtils;
import com.ehotting.eaf.core.web.domain.AjaxResult;
import com.ehotting.eaf.redis.service.RedisService;
import com.ehotting.eaf.security.service.TokenService;
import com.ehotting.eaf.core.domain.model.LoginUser;
import com.ehotting.edsta.system.api.RemoteDictService;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.websocket.AuthenticationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.ehotting.edsta.auth.form.LoginBody;
import com.ehotting.edsta.auth.form.RegisterBody;
import com.ehotting.edsta.auth.service.impl.SysLoginService;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * token 控制
 *
 * @author edsta
 */
@Slf4j
@RestController
public class TokenController
{
    @Autowired
    private TokenService tokenService;

    @Autowired
    private RedisService redisService;

    @Autowired
    private SysLoginService sysLoginService;

    @Autowired
    private RemoteDictService remoteDictService;

    @PostMapping("login")
    public R<?> login(@RequestBody LoginBody form) throws AuthenticationException {
        // 用户登录
        String username = form.getUsername();
        LoginUser userInfo = sysLoginService.login(form);
        // 判断用户类型，如果是C端，则不允许异地同时登录，如果是管理端用户，则放行
        SysUser sysUser = userInfo.getSysUser();
        String userType = sysUser.getUserType();
        // 单点登录，顶号处理
        if (UserTypeEnum.client.getType().equals(userType)){
            String key = CacheConstants.LOGIN_USER_KEY + username;
            if (redisService.hasKey(key)){
                log.warn("删除用户[{}]的上一个token", username);
                String token = redisService.get(key);
                delUserCache(token, username);
                sysLoginService.recordLogininfor(username, Constants.LOGOUT, "异地同时登录");
            }
        }

        // 校验密码长时间是否未更新
        Date pwdUpdateTime = sysUser.getPwdUpdateTime();
        int gap = getGap();
        Map<String, Object> token = tokenService.createToken(userInfo);
        if (!sysUser.isAdmin() && (pwdUpdateTime == null || DateUtils.getDiffDays(pwdUpdateTime,new Date())>gap)) {
            // 如果不是超级管理员，如果数据库的密码更新时间为空或者超过配置的阈值
            R<Map<String, Object>> result = new R<>();
            result.setCode(201);
            result.setData(token);
            result.setMsg("密码已超过"+gap+"天未更新，为了账户安全，需要立即更新密码");
            return result;
        }

        return R.ok(token);
    }

    /**
     * 获取数据库配置的密码更新时间间隔
     * 默认值为30天
     * @return
     */
    private int getGap() {
        int defaultResult = 90;

//        AjaxResult result = remoteDictService.dictType("pwd_update_time_gap", SecurityConstants.INNER);
//        if (result.get(AjaxResult.CODE_TAG).toString().equals(String.valueOf(HttpStatus.ERROR))){
//            return defaultResult;
//        }
//        if (result.get(AjaxResult.DATA_TAG) == null){
//            return defaultResult;
//        }
//
//        String json = JSONObject.toJSONString(result.get(AjaxResult.DATA_TAG));
//        List<SysDictData> sysDictDataList = JSONObject.parseArray(json, SysDictData.class);
//        if (CollectionUtils.isEmpty(sysDictDataList)){
//            return defaultResult;
//        }
//
//        try{
//            defaultResult = Integer.parseInt(sysDictDataList.get(0).getDictValue());
//        }catch (Exception e){
//            log.error("获取数据库阈值失败:",e);
//        }
        return defaultResult;
    }

    @DeleteMapping("logout")
    public R<?> logout(HttpServletRequest request)
    {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser))
        {
            String username = loginUser.getUsername();
            String token = loginUser.getToken();
            // 删除用户缓存记录
            delUserCache(token, username);
            // 记录用户退出日志
            sysLoginService.logout(username);
        }
        return R.ok();
    }

    /**
     * 删除用户缓存记录
     * @param token
     * @param username
     */
    private void delUserCache(String token, String username) {
        tokenService.delLoginUser(token);
        tokenService.delLoginToken(username);
    }

    @PostMapping("refresh")
    public R<?> refresh(HttpServletRequest request)
    {
        LoginUser loginUser = tokenService.getLoginUser(request);
        if (StringUtils.isNotNull(loginUser))
        {
            // 刷新令牌有效期
            tokenService.refreshToken(loginUser);
            return R.ok();
        }
        return R.ok();
    }

    @PostMapping("register")
    public R<?> register(@RequestBody RegisterBody registerBody)
    {
        // 用户注册
        sysLoginService.register(registerBody.getUsername(), registerBody.getPassword());
        return R.ok();
    }
}
